package de.hwrberlin.remo.logging;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.part.ViewPart;

public class ConsoleView extends ViewPart {

	private static final String LOGGER_NAME = "de.hwrberlin.remo";
	private ConsoleViewAppender logAppender;
	
	private Level[] LOGGING_LEVELS = new Level[] 
	                { Level.ALL, Level.TRACE, Level.DEBUG, Level.INFO, Level.WARN, Level.ERROR, Level.FATAL, Level.OFF };
	
	private StyledText loggingText;
	private ComboViewer comboLoggingLevel;
	
	@Override
	public void createPartControl(Composite parent) {
		GridLayoutFactory gridLayoutFactory = GridLayoutFactory.fillDefaults();
		gridLayoutFactory.numColumns(3);
		gridLayoutFactory.spacing(3, 3);
		parent.setLayout(gridLayoutFactory.create());

		Label labelLevel = new Label(parent, SWT.NONE);
		labelLevel.setText(" Level:");
		
		comboLoggingLevel = new ComboViewer(parent, SWT.SINGLE | SWT.READ_ONLY);
		comboLoggingLevel.setContentProvider(new ArrayContentProvider());
		comboLoggingLevel.setLabelProvider(loggingLevelLabelProvider);
		comboLoggingLevel.setInput(LOGGING_LEVELS);
		comboLoggingLevel.addSelectionChangedListener(comboSelectionListener);

		// ---------------------------------------------------------------------------------
		
		Button buttonClear = new Button(parent, SWT.PUSH);
		buttonClear.setText("Clear");
		buttonClear.addSelectionListener(buttonSelectionListener);
		
		GridDataFactory buttonGridData = GridDataFactory.fillDefaults();
		buttonGridData = buttonGridData.align(SWT.RIGHT, SWT.TOP).grab(true, false);
		buttonClear.setLayoutData(buttonGridData.create());
		
		// ---------------------------------------------------------------------------------
		
		loggingText = new StyledText(parent, SWT.MULTI | SWT.V_SCROLL | SWT.READ_ONLY | SWT.BORDER);
		loggingText.append("");
		
		GridDataFactory textGridData = GridDataFactory.fillDefaults();
		textGridData = textGridData.grab(true, true).span(3, 1);
		loggingText.setLayoutData(textGridData.create());
		
		// ///////////////////////////////////////////////////////////////////////////////
		
		// Add logging appender to logger
		Logger logger = Logger.getLogger(LOGGER_NAME);
		logAppender = new ConsoleViewAppender(loggingText);
		logger.addAppender(logAppender);
		
		if (logger.getLevel() == null) {
			logger.setLevel(Level.ALL);
		}
		StructuredSelection selection = new StructuredSelection(logger.getLevel());
		comboLoggingLevel.setSelection(selection);
	}
	
	@Override
	public void dispose() {
		Logger logger = Logger.getLogger("de.hwrberlin.remo");
		logger.removeAppender(logAppender);
	}

	@Override
	public void setFocus() {
		loggingText.setFocus();
	}
	
	////////////////////////
	/* Helper methods     */
	
	private LabelProvider loggingLevelLabelProvider = new LabelProvider() {
		public String getText(Object element) {
			return element.toString();
		};
	};
	
	private ISelectionChangedListener comboSelectionListener = new ISelectionChangedListener() {
		
		@Override
		public void selectionChanged(SelectionChangedEvent event) {
			ISelection selection = comboLoggingLevel.getSelection();
			
			if(selection != null && !selection.isEmpty() && selection instanceof IStructuredSelection) {
				IStructuredSelection strucSelection = (IStructuredSelection) selection;
				Object element = strucSelection.getFirstElement();
				
				if(element != null && element instanceof Level) {
					Logger logger = Logger.getLogger(LOGGER_NAME);
					logger.setLevel((Level) element);
				}
			}
		}
	};
	
	private SelectionListener buttonSelectionListener = new SelectionAdapter() {
		public void widgetSelected(SelectionEvent e) {
			loggingText.setText("");
		};
	};
}